package nl.cypherpunk.proLearner;

import net.automatalib.words.Word;
import nl.cypherpunk.proLearner.fuzzing.SUT;

import java.io.*;
import java.util.*;

public class Common {
    public void Common(){};
    public static String byteToHex(byte[] bytes){
        String strHex = "";
        StringBuilder sb = new StringBuilder("");
        for (int n = 0; n < bytes.length; n++) {
            strHex = Integer.toHexString(bytes[n] & 0xFF);
            sb.append((strHex.length() == 1) ? "0" + strHex : strHex);
        }
        return sb.toString().trim();
    }

    public static Integer getRandomState(ArrayList<Double> map) {
        NavigableMap<Double, Integer> hashMap = new TreeMap<>();
        double total = 0;
        for (int i = 0 ; i < map.size(); i++ ) {
            total += map.get(i);
            hashMap.put(total,i);
        }
        Random random =new Random();
        Double weight = 1.0*random.nextInt((int)total);
        return hashMap.ceilingEntry(weight).getValue();
    }

    //list deepCopy
    public static <T> List<T> deepCopy(List<T> src)
            throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(src);
        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream in = new ObjectInputStream(byteIn);
        return (List<T>) in.readObject();
    }


    /**
     * int到byte[] 由高位到低位
     *
     * @param i 需要转换为byte数组的整行值。
     * @return byte数组
     */
    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        result[3] = (byte) ((i >> 24) & 0xFF);
        result[2] = (byte) ((i >> 16) & 0xFF);
        result[1] = (byte) ((i >> 8) & 0xFF);
        result[0] = (byte) (i & 0xFF);
        return result;
    }

    /**
     * byte[]转int
     * @param bytes 需要转换成int的数组
     * @return int值
     */
    public static int byteArrayToInt(byte[] bytes) {
        int value=0;
        for(int i = 0; i < 4; i++) {
            int shift= i * 8;
            value +=(bytes[i] & 0xFF) << shift;
        }
        return value;
    }

    public static Integer getRandomSeed(ArrayList<Double> map){
        NavigableMap<Double, Integer> hashMap = new TreeMap<>();
        double total = 0;
        for (int i = 0; i < map.size(); i++) {
            total += map.get(i);
            hashMap.put(total, i);
        }
        Random random = new Random();
        Double weight = 1.0 * random.nextInt((int) total);
        return hashMap.ceilingEntry(weight).getValue();
    }

    public static ArrayList<List<byte[]>> readFromFile(String dir)
    {
        List<String> files = new ArrayList<String>();
        File file = new File(dir);
        if(file.length()==0)
            return null;
        ArrayList<List<byte[]>> seedPool = new ArrayList<>();
        File[] tempList = file.listFiles();
        List fileList = Arrays.asList(tempList);
        Collections.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                if (o1.isDirectory() && o2.isFile())
                    return -1;
                if (o1.isFile() && o2.isDirectory())
                    return 1;
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (int i = 0; i < tempList.length; i++) {
            if (tempList[i].isFile()) {
                files.add(tempList[i].toString());
                File temp = new File(tempList[i].toString());
                try {
                    InputStream fileIn = new FileInputStream(temp);
                    //DataInputStream in = new DataInputStream(fileIn);

                    // 使用缓存区读入对象效率更快
                    BufferedInputStream in = new BufferedInputStream(fileIn);
                    byte[] len = new byte[1024] ;
                    int length;
                    List<byte[]> seed = new ArrayList<>();
                    Word<String> inputList = Word.epsilon();
                    while(in.read(len,0,4)!=-1)
                    {
                        length = byteArrayToInt(len);
                        byte[] bys = new byte[length];
                        in.read(bys,0,length);
                        seed.add(bys);
                    }
                    in.close();
                    fileIn.close();
                    seedPool.add(seed);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
        return seedPool;
    }


}
